package com.tjcd.project.library_base.base.network;

import android.app.Application;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

import androidx.annotation.Nullable;

import com.blankj.utilcode.util.LogUtils;
import com.google.gson.JsonSyntaxException;
import com.hjq.gson.factory.GsonFactory;
import com.hjq.http.EasyLog;
import com.hjq.http.config.IRequestHandler;
import com.hjq.http.exception.CancelException;
import com.hjq.http.exception.DataException;
import com.hjq.http.exception.HttpException;
import com.hjq.http.exception.NetworkException;
import com.hjq.http.exception.NullBodyException;
import com.hjq.http.exception.ResponseException;
import com.hjq.http.exception.ServerException;
import com.hjq.http.exception.TimeoutException;
import com.hjq.http.request.HttpRequest;
import com.tjcd.project.library_base.base.bean.BaseHttpBean;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

import io.reactivex.annotations.NonNull;
import okhttp3.Headers;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * @Author jiangKunKun
 * @CreateDate 2022/7/27
 * @Description
 * @SpittingGrooves
 */
public class RequestHandler implements IRequestHandler {
    private final Application mApplication;

    public RequestHandler(Application application) {
        mApplication = application;
    }

    @androidx.annotation.NonNull
    @Override
    public Object requestSuccess(@androidx.annotation.NonNull HttpRequest<?> httpRequest, @androidx.annotation.NonNull Response response, @androidx.annotation.NonNull Type type) throws Exception {
        if (Response.class.equals(type)) {
            return response;
        }

        if (!response.isSuccessful()) {
            LogUtils.e("http响应错误", response.code(), response.message(), response.body().string());
        }

        if (Headers.class.equals(type)) {
            return response.headers();
        }

        ResponseBody body = response.body();
        if (body == null) {
            LogUtils.e("http响应空体");
        }

        if (ResponseBody.class.equals(type)) {
            return body;
        }

        // 如果是用数组接收，判断一下是不是用 byte[] 类型进行接收的
        if(type instanceof GenericArrayType) {
            Type genericComponentType = ((GenericArrayType) type).getGenericComponentType();
            if (byte.class.equals(genericComponentType)) {
                return body.bytes();
            }
        }

        if (InputStream.class.equals(type)) {
            return body.byteStream();
        }

        if (Bitmap.class.equals(type)) {
            return BitmapFactory.decodeStream(body.byteStream());
        }

        String text;
        try {
            text = body.string();
        } catch (IOException e) {
            // 返回结果读取异常
            throw new DataException("http数据解释错误", e);
        }

        // 打印这个 Json 或者文本
        EasyLog.printJson(httpRequest, text);

        if (String.class.equals(type)) {
            return text;
        }

        final Object result;

        try {
            result = GsonFactory.getSingletonGson().fromJson(text, type);
        } catch (JsonSyntaxException e) {
            // 返回结果读取异常
            throw new DataException("http数据解释错误", e);
        }

        if (result instanceof BaseHttpBean) {
            BaseHttpBean<?> model = (BaseHttpBean<?>) result;
            if ("200".equals(model.getCode())){
                // 代表执行成功
                return result;
            }else {
                LogUtils.e(model.toString());
            }
        }
        return result;
    }

    @androidx.annotation.NonNull
    @Override
    public Throwable requestFail(@androidx.annotation.NonNull HttpRequest<?> httpRequest, @androidx.annotation.NonNull Throwable e) {
        if (e instanceof HttpException) {
            return new HttpException(e.getMessage(), e);
        }

        if (e instanceof SocketTimeoutException) {
            return new TimeoutException("http服务器超时时间", e);
        }

        if (e instanceof UnknownHostException) {
            NetworkInfo info = ((ConnectivityManager) mApplication.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
            // 判断网络是否连接
            if (info != null && info.isConnected()) {
                // 有连接就是服务器的问题
                return new ServerException("http服务器错误", e);
            }
            // 没有连接就是网络异常
            return new NetworkException("http网络错误", e);
        }

        if (e instanceof IOException) {
            LogUtils.e("http请求取消", e.toString());
            return new CancelException("http请求取消", e);
        }

        return new HttpException(e.getMessage(), e);
    }

    @androidx.annotation.NonNull
    @Override
    public Throwable downloadFail(@androidx.annotation.NonNull HttpRequest<?> httpRequest, @androidx.annotation.NonNull Throwable throwable) {
        if (throwable instanceof ResponseException) {
            ResponseException responseException = ((ResponseException) throwable);
            Response response = responseException.getResponse();
            responseException.setMessage(String.format("http响应错误",
                    response.code(), response.message()));
            return responseException;
        } else if (throwable instanceof NullBodyException) {
            NullBodyException nullBodyException = ((NullBodyException) throwable);
            nullBodyException.setMessage("http响应空体");
            return nullBodyException;
        }
        return requestFail(httpRequest, throwable);
    }

    @Nullable
    @Override
    public Object readCache(@NonNull HttpRequest<?> httpRequest, @NonNull Type type, long cacheTime) {
        String cacheKey = HttpCacheManager.generateCacheKey(httpRequest);
        String cacheValue = HttpCacheManager.getMmkv().getString(cacheKey, null);
        if (cacheValue == null || "".equals(cacheValue) || "{}".equals(cacheValue)) {
            return null;
        }
        EasyLog.printLog(httpRequest, "----- readCache cacheKey -----");
        EasyLog.printJson(httpRequest, cacheKey);
        EasyLog.printLog(httpRequest, "----- readCache cacheValue -----");
        EasyLog.printJson(httpRequest, cacheValue);
        return GsonFactory.getSingletonGson().fromJson(cacheValue, type);
    }

    @Override
    public boolean writeCache(@NonNull HttpRequest<?> httpRequest, @NonNull Response response, @NonNull Object result) {
        String cacheKey = HttpCacheManager.generateCacheKey(httpRequest);
        String cacheValue = GsonFactory.getSingletonGson().toJson(result);
        if (cacheValue == null || "".equals(cacheValue) || "{}".equals(cacheValue)) {
            return false;
        }
        EasyLog.printLog(httpRequest, "----- writeCache cacheKey -----");
        EasyLog.printJson(httpRequest, cacheKey);
        EasyLog.printLog(httpRequest, "----- writeCache cacheValue -----");
        EasyLog.printJson(httpRequest, cacheValue);
        return HttpCacheManager.getMmkv().putString(cacheKey, cacheValue).commit();
    }

    @Override
    public boolean deleteCache(@androidx.annotation.NonNull HttpRequest<?> httpRequest) {
        return IRequestHandler.super.deleteCache(httpRequest);
    }

    @Override
    public void clearCache() {
        HttpCacheManager.getMmkv().clearMemoryCache();
        HttpCacheManager.getMmkv().clearAll();
    }

    @Override
    public Type getGenericType(Object object) {
        return IRequestHandler.super.getGenericType(object);
    }
}
